/*
 * Copyright © 2021 尛飛俠（Denvie） All rights reserved.
 */

package cn.denvie.springboot.mbp.generator;

import cn.denvie.springboot.mbp.generator.properties.GenerateProperties;
import cn.denvie.springboot.mbp.generator.properties.PropertiesConst;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;

import java.io.File;
import java.util.function.Consumer;

/**
 * 代码生成器抽象类。
 * <p>
 * 参考：<a href="https://gitee.com/baomidou/generator">https://gitee.com/baomidou/generator</a>
 * </p>
 *
 * @author Denvie
 * @date 2021/12/18
 * @since 1.0.0
 */
public abstract class AbstractCodeGenerator {
    private GenerateProperties properties;

    /**
     * 开始执行
     */
    public void execute() {
        this.properties = new GenerateProperties(getPropertyName());
        FastAutoGenerator.create(dataSourceConfigBuilder())
                // 全局配置
                .globalConfig(globalConfigBuilder())
                // 包配置
                .packageConfig(packageConfigBuilder())
                // 策略配置
                .strategyConfig(strategyConfigBuilder())
                // 注入配置
                .injectionConfig(injectionConfigBuilder())
                // 模板配置
                .templateEngine(new FreemarkerTemplateEngine())
                .execute();
    }

    /**
     * 获取属性文件名。
     *
     * @return 文件名
     */
    public abstract String getPropertyName();

    /**
     * 数据源配置
     */
    private DataSourceConfig.Builder dataSourceConfigBuilder() {
        return new DataSourceConfig.Builder(
                properties.getUrl(),
                properties.getUsername(),
                properties.getPassword());
    }

    /**
     * 全局配置
     */
    private Consumer<GlobalConfig.Builder> globalConfigBuilder() {
        String javaOutputDir = getJavaOutputDir();
        System.out.println("Java文件输出目录：" + javaOutputDir);
        return builder -> builder.outputDir(javaOutputDir)
                .disableOpenDir()
                .fileOverride()
                //.enableSwagger()
                .author(this.properties.getAuthor())
                .dateType(DateType.ONLY_DATE)
                .commentDate("yyyy/M/dd");
    }

    private String getJavaOutputDir() {
        return new File(System.getProperty("user.dir"))
                + File.separator + this.properties.getProjectName()
                + File.separator + this.properties.getJavaOutputDir();
    }

    /**
     * 包配置
     */
    private Consumer<PackageConfig.Builder> packageConfigBuilder() {
        return builder -> {
            builder.parent(this.properties.getPackageName())
                    .moduleName(this.properties.getModuleName())
                    .entity(this.properties.getEntityPkg())
                    .mapper(this.properties.getMapperPkg())
                    .xml(this.properties.getMapperXmlPkg())
                    .service(this.properties.getServicePkg())
                    .serviceImpl(this.properties.getServiceImplPkg())
                    .controller(this.properties.getControllerPkg());

            String javaOutputDir = getJavaOutputDir();
            String xmlOutputDir = new File(System.getProperty("user.dir"))
                    + File.separator + this.properties.getProjectName()
                    + File.separator + this.properties.getXmlOutputDir();
            System.out.println("Mapper文件输出目录：" + xmlOutputDir);
            builder.pathInfo(new PathInfoHandler(javaOutputDir, xmlOutputDir, builder.build()).getPathInfo());
        };
    }

    /**
     * 策略配置
     */
    private Consumer<StrategyConfig.Builder> strategyConfigBuilder() {
        return builder -> builder.addInclude(this.properties.getIncludeTables())
                .addTablePrefix("")
                .entityBuilder()
                .idType(IdType.ASSIGN_ID)
                .disableSerialVersionUID()
                .enableTableFieldAnnotation()
                .superClass(PropertiesConst.superEntityClass())
                .addSuperEntityColumns(PropertiesConst.superEntityColumns())
                .enableLombok()
                .formatFileName("%s")
                // 表字段下划线转驼峰命名
                .columnNaming(NamingStrategy.underline_to_camel)
                .mapperBuilder()
                .enableBaseResultMap()
                .enableBaseColumnList()
                .serviceBuilder()
                .formatServiceFileName("%s" + ConstVal.SERVICE)
                .controllerBuilder()
                .superClass(PropertiesConst.superControllerClass())
                .enableRestStyle();
    }

    /**
     * 注入配置
     */
    private Consumer<InjectionConfig.Builder> injectionConfigBuilder() {
        return builder -> builder.beforeOutputFile((tableInfo, stringObjectMap) -> {
            stringObjectMap.put("version", this.properties.getVersion());
            stringObjectMap.put("copyright", this.properties.getCopyright());
        });
    }
}
